package com.taobao.demo.user.security;


import com.taobao.demo.user.common.Result;
import com.taobao.demo.user.utils.JwtUtil;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.annotation.Resource;
import java.io.PrintWriter;

/**
 * Spring Security 配置类（定义认证规则和权限控制）
 */
@Configuration
@EnableWebSecurity // 开启Web安全配置
@EnableGlobalMethodSecurity(prePostEnabled = true) // 开启方法级权限注解（@PreAuthorize）
public class SecurityConfig {

    @Resource
    private JwtAuthFilter jwtAuthFilter; // JWT认证拦截器
    @Resource
    private JwtUtil jwtUtil; // JWT工具类

    /**
     * 密码编码器（BCrypt加密，与Service中密码加密逻辑一致）
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 认证管理器（用于处理登录认证，Spring Security自动注入）
     */
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
        return config.getAuthenticationManager();
    }

    /**
     * 核心配置：定义接口访问规则、添加JWT拦截器、关闭Session等
     */
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                // 1. 关闭CSRF（前后端分离项目，用JWT认证，无需CSRF保护）
                .csrf().disable()
                // 2. 关闭Session（JWT是无状态的，不依赖Session）
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                // 3. 定义接口访问权限规则
                .authorizeRequests()
                // 公开接口：注册、登录（无需登录即可访问）
                .antMatchers("/api/user/register", "/api/user/login").permitAll()
                // 其他所有接口：必须登录（IS_AUTHENTICATED_FULLY 表示已完全认证）
                .anyRequest().authenticated()
                .and()
                // 4. 添加JWT认证拦截器（在UsernamePasswordAuthenticationFilter之前执行）
                .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
                // 5. 配置异常处理（认证失败、权限不足时返回统一格式）
                .exceptionHandling()
                // 认证失败（未登录或Token无效）
                .authenticationEntryPoint((request, response, ex) -> {
                    response.setContentType("application/json;charset=utf-8");
                    PrintWriter out = response.getWriter();
                    out.write(Result.fail("请先登录").toString()); // 返回统一失败响应
                    out.flush();
                    out.close();
                })
                // 权限不足（如普通用户访问管理员接口）
                .accessDeniedHandler((request, response, ex) -> {
                    response.setContentType("application/json;charset=utf-8");
                    PrintWriter out = response.getWriter();
                    out.write(Result.fail("权限不足，无法访问").toString()); // 返回统一失败响应
                    out.flush();
                    out.close();
                });

        return http.build();
    }
}
